package self.security.filter;

import org.self.service.IJwtService;
import org.self.service.ITokenService;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import self.enumerate.ResponseCode;
import self.result.R;
import self.security.utils.HttpResponseUtils;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 作者: liYu
 * 标题: AuthFilter
 * 项目名字 CD-Java-2307-springboot-parent
 * 描述: 这个过滤器的主要功能两部分
 * 第一部分：判断身份是否合法
 * 第二部分：就是将权限信息和角色信息取出来 放到上下文中去校验
 */
public class AuthFilter extends BasicAuthenticationFilter {

    private ITokenService tokenService;

    private IJwtService jwtService;

    //这里需要传递这个AuthenticationManager对象过来
    public AuthFilter(AuthenticationManager authenticationManager,ITokenService tokenService, IJwtService jwtService) {
        super(authenticationManager);
        this.tokenService=tokenService;
        this.jwtService = jwtService;
    }

    /**
     * 请求资源的时候 会执行到这个方法来
     * @param request
     * @param response
     * @param chain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        //首先我们就要获取前端传递过来的这个token信息
        //前端传递token的时候 是将这个token的信息放到了 HTTP协议中的请求头中....
        //我们就要从头里面将这个信息给取出来
        String token = request.getHeader("token");
        //接下来我们就要校验这个token的合法性....
        boolean b = this.tokenService.verifyToken(token);
        if(!b){
            //说明用户token校验失败
            R error = R.error(ResponseCode.UNAUTH_EXCEPTION.getCode(),
                    ResponseCode.UNAUTH_EXCEPTION.getMessage());
            //接下来将这个数据返回去
            HttpResponseUtils.sendResponse(response,error);
            return ;
        }
        //如果程序执行到这里说明Token的身份校验是成功的
        //TODO 这里就需要通过token去内存中找到权限信息和角色信息 然后封装成authentication对象

        //接下来我们需要封装一个Authentication对象
        // 第一个参数我们可以放 id   第二个参数可以放用户户名 第三个参数可以放权限信息
        String userId=this.jwtService.getId(token);
        //获取用户名字
        String username = this.jwtService.getUsername(token);

        List<GrantedAuthority> grantedAuthorityList=new ArrayList<>();
        grantedAuthorityList.add(new SimpleGrantedAuthority("ROLE_admin"));

        //将数据封装成authenticationToken对象
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userId, username, grantedAuthorityList);

        //接下来就是将上述信息放到上下文中(目的：好判断这个用户是否有这个权限 和这个角色 访问这个方法)
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        //接下来放行
        chain.doFilter(request,response);
    }
}
